home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / login.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  24KB  |  805 lines

  1. /*
  2.  * static char *rcsid_login_c =
  3.  *   "$Id: login.c,v 1.40 1996/01/02 11:40:40 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28. #include <global.h>
  29. #ifndef __CEXTRACT__
  30. #include <sproto.h>
  31. #endif
  32. #include <spells.h>
  33.  
  34. extern spell spells[NROFREALSPELLS];
  35. extern void sub_weight (object *, signed long);
  36. extern void add_weight (object *, signed long);
  37. extern char *uncomp[NROF_COMPRESS_METHODS][3];
  38. extern char *range_name[range_size];
  39. extern long pticks;
  40.  
  41. /* If flag is non zero, it means that we want to try and save everyone, but
  42.  * keep the game running.  Thus, we don't want to free any information.
  43.  */
  44. void emergency_save(int flag) {
  45.   player *pl;
  46. #ifndef NO_EMERGENCY_SAVE
  47.   trying_emergency_save = 1;
  48.   if(editor)
  49.     return;
  50.   LOG(llevError,"Emergency save:  ");
  51.   for(pl=first_player;pl!=NULL;pl=pl->next) {
  52.     if(!pl->ob) {
  53.       LOG(llevError, "No name, ignoring this.\n");
  54.       continue;
  55.     }
  56.     LOG(llevError,"%s ",pl->ob->name);
  57.     new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save...");
  58.  
  59. /* If we are not exiting the game (ie, this is sort of a backup save), then
  60.  * don't change the location back to the village.  Note that there are other
  61.  * options to have backup saves be done at the starting village
  62.  */
  63.     if (!flag) {
  64.     strcpy(pl->maplevel, first_map_path);
  65.     if(pl->ob->map!=NULL)
  66.         pl->ob->map = NULL;
  67.     pl->ob->x = -1;
  68.     pl->ob->y = -1;
  69.     }
  70.     if(!save_player(pl->ob,flag)) {
  71.       LOG(llevError, "(failed) ");
  72.       new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score...");
  73.     }
  74.     check_score(pl->ob);
  75.   }
  76.   LOG(llevError,"\n");
  77. #else
  78.   LOG(llevError,"Emergency saves disabled, no save attempted\n");
  79. #endif
  80.   /* After we complete the emergency saves, then try and free
  81.    * the pixmaps.  Without this effort, some X-Terminals (and maybe
  82.    * even workstations) XServers will not free the space used by
  83.    * the pixmaps.  This is more of a problem for the X-Terminals,
  84.    * because they don't have a lot of memory.  The pointer is set
  85.    * to NULL after we are finished to prevent another effort later.
  86.    */
  87.   if (!flag) {
  88.     for(pl=first_player;pl!=NULL;pl=pl->next) {
  89.       if(!pl->ob) {
  90.     LOG(llevError, "No name, ignoring this.\n");
  91.     continue;
  92.       }
  93.       if (pl->pixmaps) {
  94.     free_pixmaps(pl->gdisp, pl->pixmaps);
  95.     pl->pixmaps=NULL;
  96.       }
  97.       if (pl->masks) {
  98.     free_pixmaps(pl->gdisp, pl->masks);
  99.     pl->masks =NULL;
  100.       }
  101.     }
  102.   }
  103. }
  104.  
  105. void delete_character(char *name) {
  106.   char buf[MAX_BUF];
  107.  
  108. #ifdef SAVE_HOMEDIR
  109.   sprintf(buf,"%s/%s/%s.pl",(char *) getenv("HOME"),PlayerDir,name);
  110. #else
  111.   sprintf(buf,"%s/%s/%s.pl",LibDir,PlayerDir,name);
  112. #endif
  113.   if(unlink(buf)== -1 && debug)
  114.     perror("crossfire (delete character)");
  115. }
  116.  
  117. void remove_lock(player *pl) {
  118. #ifdef LOCK_PLAYER
  119.   char buf[MAX_BUF];
  120.  
  121.   if(pl->ob == NULL)
  122.     return;
  123. #ifdef SAVE_HOMEDIR
  124.   sprintf(buf, "%s/%s", (char *) getenv("HOME"), PlayerDir);
  125.   (void) create_savedir_if_needed(buf);
  126.   
  127.   sprintf(buf,"%s/%s/%s.lock",(char *) getenv("HOME"),PlayerDir,pl->ob->name);
  128. #else
  129.   sprintf(buf,"%s/%s/%s.lock",LibDir,PlayerDir,pl->ob->name);
  130. #endif
  131.   if(!rmdir(buf)) {
  132. #ifdef DEBUG
  133.     perror("Couldn't remove lockfile(dir)");
  134. #endif
  135.   }
  136. #endif
  137. }
  138.  
  139. int lock_player(char *name) {
  140. #ifdef LOCK_PLAYER
  141.   char buf[MAX_BUF];
  142.  
  143. #ifdef SAVE_HOMEDIR
  144.   sprintf(buf, "%s/%s", (char *) getenv("HOME"), PlayerDir);
  145.   (void) create_savedir_if_needed(buf);
  146.   
  147.   sprintf(buf,"%s/%s/%s.lock",(char *) getenv("HOME"),PlayerDir,name);
  148. #else
  149.   sprintf(buf,"%s/%s/%s.lock",LibDir,PlayerDir,name);
  150. #endif
  151.   if(!mkdir(buf,0770))
  152.     return 0;
  153.   if(errno != EEXIST) {
  154.     perror("Couldn't create lockfile(dir)");
  155.     return 1;
  156.   }
  157.   return 1;
  158. #else
  159.   return 0;
  160. #endif
  161. }
  162.  
  163. int check_name(player *me,char *name) {
  164.   player *pl;
  165.  
  166. #ifdef ONE_PLAYER_PR_UID
  167.   if (me->username == NULL)
  168.     LOG(llevError, "Player had no username.\n");
  169.   else
  170.     for (pl = first_player; pl != NULL; pl = pl->next)
  171.       if (pl != me && pl->username != NULL &&
  172.           !strcmp(pl->username, me->username)) {
  173.         new_draw_info(NDI_UNIQUE, 0,me->ob, "You are already playing the game.");
  174.         return 0;
  175.       }
  176. #endif
  177.   for(pl=first_player;pl!=NULL;pl=pl->next)
  178.     if(pl!=me&&pl->ob->name!=NULL&&!strcmp(pl->ob->name,name)) {
  179.       new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is already in use.");
  180.       return 0;
  181.     }
  182.   if(lock_player(name)) {
  183.     new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is already in use.");
  184.     return 0;
  185.   }
  186.   if(!playername_ok(name)) {
  187.     new_draw_info(NDI_UNIQUE, 0,me->ob,"That name contains illegal characters.");
  188.     remove_lock(me);
  189.     return 0;
  190.   }
  191.   return 1;
  192. }
  193.  
  194. int create_savedir_if_needed(char *savedir)
  195. {
  196.   struct stat *buf;
  197.  
  198.   if ((buf = (struct stat *) malloc(sizeof(struct stat))) == NULL) {
  199.     perror("Unable to save playerfile... out of memory.");
  200.     return 0;
  201.   } else {
  202.     stat(savedir, buf);
  203.     if ((buf->st_mode & S_IFDIR) == 0)
  204. #if defined(_IBMR2) || defined(___IBMR2)
  205.       if (mkdir(savedir, S_ISUID|S_ISGID|S_IRUSR|S_IWUSR|S_IXUSR))
  206. #else
  207.       if (mkdir(savedir, S_ISUID|S_ISGID|S_IREAD|S_IWRITE|S_IEXEC))
  208. #endif
  209.     {
  210.     perror("Unable to create player savedir,");
  211.     perror(savedir);
  212.     return 0;
  213.       }
  214.     free(buf);
  215.   }
  216.  return 1;
  217. }
  218.  
  219. void destroy_object (object *op)
  220. {
  221.     object *tmp;
  222.     while ((tmp = op->inv))
  223.     destroy_object (tmp);
  224.     if (!QUERY_FLAG(op, FLAG_REMOVED))
  225.     remove_ob(op);
  226.     free_object(op);
  227. }
  228.  
  229. /*
  230.  * If flag is set, it's only backup, ie dont remove objects from inventory
  231.  * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player
  232.  * will be saved at the emergency save location.
  233.  * Returns non zero if successful.
  234.  */
  235.  
  236. int save_player(object *op, int flag) {
  237.   FILE *fp;
  238.   char filename[MAX_BUF], *tmpfilename,backupfile[MAX_BUF];
  239.   object *tmp, *container=NULL;
  240.   player *pl = op->contr;
  241.   int i;
  242.   long checksum;
  243. #ifdef BACKUP_SAVE_AT_HOME
  244.   sint16 backup_x, backup_y;
  245. #endif
  246.  
  247.   flag&=1;
  248.  
  249.   if(QUERY_FLAG(op,FLAG_WAS_WIZ)||!pl->name_changed||(!flag&&!op->stats.exp)) {
  250.     if(!flag) {
  251.       new_draw_info(NDI_UNIQUE, 0,op,"Your name is not valid,");
  252.       new_draw_info(NDI_UNIQUE, 0,op,"Game not saved.");
  253.     }
  254.     return 0;
  255.   }
  256.  
  257.   if (flag == 0)
  258.     terminate_all_pets(op);
  259.  
  260. #ifdef SAVE_HOMEDIR
  261.   sprintf(filename,"%s/%s", (char *) getenv("HOME"), PlayerDir);
  262.   (void) create_savedir_if_needed(filename);
  263.   
  264.   sprintf(filename,"%s/%s/%s.pl",(char *) getenv("HOME"),PlayerDir,op->name);
  265. #else
  266.   sprintf(filename,"%s/%s/%s.pl",LibDir,PlayerDir,op->name);
  267. #endif
  268.   tmpfilename = tempnam(TMPDIR,NULL);
  269.   fp=fopen(tmpfilename, "w");
  270.   if(!fp) {
  271.     new_draw_info(NDI_UNIQUE, 0,op, "Can't open file for save.");
  272.     free(tmpfilename);
  273.     return 0;
  274.   }
  275.  
  276. /* Eneq(@csd.uu.se): If we have an open container hide it. */
  277.    if (op->container)  {
  278.      container=op->container;
  279.        op->container=NULL;
  280.    }
  281.  
  282.   fprintf(fp,"password %s\n",pl->password);
  283. #ifdef SET_TITLE
  284.   if(pl->own_title[0]!='\0')
  285.     fprintf(fp,"title %s\n",pl->own_title);
  286. #endif /* SET_TITLE */
  287. #ifdef SAVE_WINDOW_POSITIONS
  288.   if(pl->valid_save_positions && pl->split_window) {
  289.     fprintf(fp,"win_pos");
  290.     for(i=0;i<6;i++)
  291.       fprintf(fp," %d %d %u %u",
  292.           pl->win_pos[i].x,pl->win_pos[i].y,
  293.           pl->win_pos[i].w,pl->win_pos[i].h);
  294.     fprintf(fp,"\n");
  295.   }
  296. #endif /* SAVE_WINDOW_POSITIONS */
  297. #ifdef EXPLORE_MODE
  298.   fprintf(fp,"explore %d\n",pl->explore);
  299. #endif
  300.   fprintf(fp,"gen_hp %d\n",pl->gen_hp);
  301.   fprintf(fp,"gen_sp %d\n",pl->gen_sp);
  302.   fprintf(fp,"gen_grace %d\n",pl->gen_grace);
  303.   fprintf(fp,"listening %d\n",pl->listening);
  304.   fprintf(fp,"spell %d\n",pl->chosen_spell);
  305.   fprintf(fp,"shoottype %d\n",pl->shoottype);
  306.   fprintf(fp,"berzerk %d\n",pl->berzerk);
  307.   fprintf(fp,"peaceful %d\n",pl->peaceful);
  308.   fprintf(fp,"scroll %d\n",pl->scroll);
  309.   fprintf(fp,"digestion %d\n",pl->digestion);
  310.   fprintf(fp,"pickup %d\n", pl->mode);
  311.   fprintf(fp,"keyboard_flush %d\n", pl->keyboard_flush);
  312.   fprintf(fp,"show_inv_icon %d\n", pl->show_inv_icon);
  313.   fprintf(fp,"outputs_sync %d\n", pl->outputs_sync);
  314.   fprintf(fp,"outputs_count %d\n", pl->outputs_count);
  315.  
  316. #ifdef BACKUP_SAVE_AT_HOME
  317.   if (op->map!=NULL && flag==0)
  318. #else
  319.   if (op->map!=NULL)
  320. #endif
  321.     fprintf(fp,"map %s\n",op->map->path);
  322.   else
  323.     fprintf(fp,"map %s\n",first_map_path);
  324.   fprintf(fp,"weapon_sp %f\n",pl->weapon_sp);
  325.   fprintf(fp,"Str %d\n",pl->orig_stats.Str);
  326.   fprintf(fp,"Dex %d\n",pl->orig_stats.Dex);
  327.   fprintf(fp,"Con %d\n",pl->orig_stats.Con);
  328.   fprintf(fp,"Int %d\n",pl->orig_stats.Int);
  329.   fprintf(fp,"Pow %d\n",pl->orig_stats.Pow);
  330.   fprintf(fp,"Wis %d\n",pl->orig_stats.Wis);
  331.   fprintf(fp,"Cha %d\n",pl->orig_stats.Cha);
  332.  
  333.   dump_keys(pl, fp);
  334.  
  335.   fprintf(fp,"lev_array %d\n",op->level>10?10:op->level);
  336.   for(i=1;i<=pl->last_level&&i<=10;i++) {
  337.     fprintf(fp,"%d\n",pl->levhp[i]);
  338.     fprintf(fp,"%d\n",pl->levsp[i]);
  339.      fprintf(fp,"%d\n",pl->levgrace[i]);
  340.   }
  341.   for(i=0;i<pl->nrofknownspells;i++)
  342.     fprintf(fp,"known_spell %s\n",spells[pl->known_spells[i]].name);
  343.   fprintf(fp,"endplst\n");
  344.  
  345.   pl->freeze_inv = 1;
  346.   SET_FLAG(op, FLAG_NO_FIX_PLAYER);
  347. #ifdef BACKUP_SAVE_AT_HOME
  348.   if (flag) {
  349.     backup_x = op->x;
  350.     backup_y = op->y;
  351.     op->x = -1;
  352.     op->y = -1;
  353.   }
  354.   /* Save objects, but not unpaid objects.  Don't remove objects from
  355.    * inventory.
  356.    */
  357.   save_object(fp, op, 2);
  358.   if (flag) {
  359.     op->x = backup_x;
  360.     op->y = backup_y;
  361.   }
  362. #else
  363.   save_object(fp, op, 3); /* don't check and don't remove */
  364. #endif
  365.  
  366.   CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER);
  367.  
  368.   if(!flag)
  369.       while ((tmp = op->inv))
  370.       destroy_object (tmp);
  371.  
  372.   if (fclose(fp) == EOF) {    /* make sure the write succeeded */
  373.     new_draw_info(NDI_UNIQUE, 0,op, "Can't save character.");
  374.     unlink(tmpfilename);
  375.     free(tmpfilename);
  376.     return 0;
  377.   }
  378.   checksum = calculate_checksum(tmpfilename, 0);
  379.   sprintf(backupfile, "%s.tmp", filename);
  380.   rename(filename, backupfile);
  381.   fp = fopen(filename,"w");
  382.   if(!fp) {
  383.     new_draw_info(NDI_UNIQUE, 0,op, "Can't open file for save.");
  384.     unlink(tmpfilename);
  385.     free(tmpfilename);
  386.     return 0;
  387.   }
  388.   fprintf(fp,"checksum %lx\n",checksum);
  389.   copy_file(tmpfilename, fp);
  390.   unlink(tmpfilename);
  391.   free(tmpfilename);
  392.   if (fclose(fp) == EOF) {    /* got write error */
  393.     new_draw_info(NDI_UNIQUE, 0,op, "Can't close file for save.");
  394.     rename(backupfile, filename); /* Restore the original */
  395.     return 0;
  396.   }
  397.   else
  398.     unlink(backupfile);
  399.  
  400.   pl->freeze_inv=0;
  401.  
  402.   /* Eneq(@csd.uu.se): Reveal the container if we have one. */
  403.   if (flag&&container!=NULL) 
  404.     op->container = container;
  405.  
  406.   if(!flag)
  407.     if (op->contr->eric_server > 0)
  408.     esrv_send_inventory(op, op);
  409.     else
  410.     draw_all_inventory(op);
  411.  
  412.   chmod(filename,SAVE_MODE);
  413.   return 1;
  414. }
  415.  
  416. /*
  417.  * calculate_checksum:
  418.  * Evil scheme to avoid tampering with the player-files 8)
  419.  * The cheat-flag will be set if the file has been changed.
  420.  */
  421.  
  422. long calculate_checksum(char *filename, int checkdouble) {
  423. #ifdef USE_CHECKSUM
  424.   long checksum = 0;
  425.   int offset = 0;
  426.   FILE *fp;
  427.   char buf[MAX_BUF], *cp;
  428.   if ((fp = fopen(filename,"r")) == NULL)
  429.     return 0;
  430.   while(fgets(buf,MAX_BUF,fp)) {
  431.     if(checkdouble && !strncmp(buf,"checksum",8))
  432.       continue;
  433.     for(cp=buf;*cp;cp++) {
  434.       if(++offset>28)
  435.         offset = 0;
  436.       checksum^=(*cp<<offset);
  437.     }
  438.   }
  439.   fclose(fp);
  440.   return checksum;
  441. #else
  442.   return 0;
  443. #endif
  444. }
  445.  
  446. void copy_file(char *filename, FILE *fpout) {
  447.   FILE *fp;
  448.   char buf[MAX_BUF];
  449.   if((fp = fopen(filename,"r")) == NULL)
  450.     return;
  451.   while(fgets(buf,MAX_BUF,fp)!=NULL)
  452.     fputs(buf,fpout);
  453.   fclose(fp);
  454. }
  455.  
  456. #if 1
  457. static int spell_sort(const void *a1,const void *a2)
  458. {
  459.   return strcmp(spells[(int)*(sint16 *)a1].name,spells[(int)*(sint16 *)a2].name);
  460. }
  461. #else
  462. static int spell_sort(const char *a1,const char *a2)
  463. {
  464.    fprintf(stderr, "spell1=%d, spell2=%d\n", *(sint16*)a1, *(sint16*)a2);
  465.   return strcmp(spells[(int )*a1].name,spells[(int )*a2].name);
  466. }
  467. #endif
  468.  
  469. void check_login(object *op) {
  470.   FILE *fp;
  471.   char filename[MAX_BUF];
  472.   char buf[MAX_BUF],bufall[MAX_BUF];
  473.   int i,value,x,y,comp;
  474.   long checksum = 0;
  475.   player *pl = op->contr;
  476.  
  477.   strcpy (pl->maplevel, first_map_path);
  478. #ifdef SAVE_HOMEDIR
  479.   sprintf(filename,"%s/%s/%s.pl",(char *) getenv("HOME"),PlayerDir,op->name);
  480. #else
  481.   sprintf(filename,"%s/%s/%s.pl",LibDir,PlayerDir,op->name);
  482. #endif
  483.   if ((fp=open_and_uncompress(filename,1,&comp)) == NULL) {
  484.     confirm_password(op);
  485.   } else {
  486.     int correct = 0;
  487.     if(fgets(bufall,MAX_BUF,fp) != NULL) {
  488.       if(!strncmp(bufall,"checksum ",9)) {
  489.         checksum = strtol_local(bufall+9,(char **) NULL, 16);
  490.         (void) fgets(bufall,MAX_BUF,fp);
  491.       }
  492.       if(sscanf(bufall,"password %s\n",buf))
  493.         /* New password scheme: */
  494.         correct=check_password(pl->write_buf+1,buf);
  495.       else { /* Old scheme when passwords were stored in ascii */
  496.         bufall[strlen(bufall)-1]='\0';
  497.         correct= !strcmp(bufall,pl->write_buf+1);
  498.       }
  499.     }
  500.     if (!correct) {
  501.       new_draw_info(NDI_UNIQUE, 0,op," ");
  502.       new_draw_info(NDI_UNIQUE, 0,op,"Wrong Password!");
  503.       new_draw_info(NDI_UNIQUE, 0,op," ");
  504.       remove_lock(pl);
  505.       if(op->name!=NULL)
  506.         free_string(op->name);
  507.       op->name=add_string("noname");
  508.       pl->last_value= -1;
  509.       draw_stats(op);
  510.       get_name(op);
  511.     } else {
  512. #ifdef SAVE_INTERVAL
  513.       pl->last_save_time=time(NULL);
  514. #endif /* SAVE_INTERVAL */
  515. #ifdef SIMPLE_PARTY_SYSTEM
  516.       pl->party_number = (-1);
  517. #endif /* SIMPLE_PARTY_SYSTEM */
  518. #ifdef SAVE_WINDOW_POSITIONS
  519.       pl->valid_save_positions=0;
  520. #endif /* SAVE_WINDOW_POSITIONS */
  521. #ifdef SEARCH_ITEMS
  522.       pl->search_str[0]='\0';
  523. #endif /* SEARCH_ITEMS */
  524.       pl->name_changed=1;
  525.       pl->orig_stats.Str=0;
  526.       pl->orig_stats.Dex=0;
  527.       pl->orig_stats.Con=0;
  528.       pl->orig_stats.Int=0;
  529.       pl->orig_stats.Pow=0;
  530.       pl->orig_stats.Wis=0;
  531.       pl->orig_stats.Cha=0;
  532.       load_default_keys(op->contr);
  533.       while (fgets(bufall,MAX_BUF,fp)!=NULL) {
  534.         sscanf(bufall,"%s %d\n",buf,&value);
  535.         if (!strcmp(buf,"endplst"))
  536.           break;
  537. #ifdef SET_TITLE
  538.     else if (!strncmp(bufall,"title",6))
  539.           sscanf(bufall,"title %s[^\n]",pl->own_title);
  540. #endif /* SET_TITLE */
  541. #ifdef SAVE_WINDOW_POSITIONS
  542.     else if (!strcmp(buf,"win_pos") && pl->split_window) {
  543.       pl->valid_save_positions=
  544.         (sscanf(bufall,
  545.             "win_pos %d %d %u %u %d %d %u %u %d %d %u %u %d %d %u %u %d %d %u %u %d %d %u %u",
  546.             &pl->win_pos[0].x,&pl->win_pos[0].y,
  547.             &pl->win_pos[0].w,&pl->win_pos[0].h,
  548.             &pl->win_pos[1].x,&pl->win_pos[1].y,
  549.             &pl->win_pos[1].w,&pl->win_pos[1].h,
  550.             &pl->win_pos[2].x,&pl->win_pos[2].y,
  551.             &pl->win_pos[2].w,&pl->win_pos[2].h,
  552.             &pl->win_pos[3].x,&pl->win_pos[3].y,
  553.             &pl->win_pos[3].w,&pl->win_pos[3].h,
  554.             &pl->win_pos[4].x,&pl->win_pos[4].y,
  555.             &pl->win_pos[4].w,&pl->win_pos[4].h,
  556.             &pl->win_pos[5].x,&pl->win_pos[5].y,
  557.             &pl->win_pos[5].w,&pl->win_pos[5].h)==24);
  558.     }
  559. #endif /* SAVE_WINDOW_POSITIONS */
  560. #ifdef EXPLORE_MODE
  561.       else if (!strcmp(buf,"explore"))
  562.         pl->explore = value;
  563. #endif
  564.         else if (!strcmp(buf,"gen_hp"))
  565.           pl->gen_hp=value;
  566.         else if (!strcmp(buf,"shoottype"))
  567.           pl->shoottype=(rangetype)value;
  568.         else if (!strcmp(buf,"gen_sp"))
  569.           pl->gen_sp=value;
  570.         else if (!strcmp(buf,"gen_grace"))
  571.           pl->gen_grace=value;
  572.         else if (!strcmp(buf,"spell"))
  573.           pl->chosen_spell=value;
  574.         else if (!strcmp(buf,"listening"))
  575.           pl->listening=value;
  576.         else if (!strcmp(buf,"berzerk"))
  577.           pl->berzerk=value;
  578.         else if (!strcmp(buf,"peaceful"))
  579.           pl->peaceful=value;
  580.         else if (!strcmp(buf,"scroll"))
  581.           pl->scroll=value;
  582.         else if (!strcmp(buf,"digestion"))
  583.           pl->digestion=value;
  584.     else if (!strcmp(buf,"pickup"))
  585.       pl->mode=value;
  586.         else if (!strcmp(buf,"keyboard_flush"))
  587.       pl->keyboard_flush = value;
  588.         else if (!strcmp(buf,"show_inv_icon")) {
  589.       pl->show_inv_icon = value;
  590.       if (pl->show_inv_icon)
  591.         strcpy(pl->format_inv,"%-20.20s%-6s"); /* This can be changed by resize */
  592.       else
  593.         strcpy(pl->format_inv,"%-24.24s%-6s"); /* This can be changed by resize */
  594.     }
  595.     else if (!strcmp(buf,"outputs_sync"))
  596.       pl->outputs_sync = value;
  597.     else if (!strcmp(buf,"outputs_count"))
  598.       pl->outputs_count = value;
  599.         else if (!strcmp(buf,"map"))
  600.         sscanf(bufall,"map %s", pl->maplevel);
  601.         else if (!strcmp(buf,"weapon_sp"))
  602.           sscanf(buf,"weapon_sp %f",&pl->weapon_sp);
  603.         else if (!strcmp(buf,"Str"))
  604.           pl->orig_stats.Str=value;
  605.         else if (!strcmp(buf,"Dex"))
  606.           pl->orig_stats.Dex=value;
  607.         else if (!strcmp(buf,"Con"))
  608.           pl->orig_stats.Con=value;
  609.         else if (!strcmp(buf,"Int"))
  610.           pl->orig_stats.Int=value;
  611.         else if (!strcmp(buf,"Pow"))
  612.           pl->orig_stats.Pow=value;
  613.         else if (!strcmp(buf,"Wis"))
  614.           pl->orig_stats.Wis=value;
  615.         else if (!strcmp(buf,"Cha"))
  616.           pl->orig_stats.Cha=value;
  617.         else if (!strcmp(buf,"lev_array")){
  618.           for(i=1;i<=value;i++) {
  619.             int j;
  620.             fscanf(fp,"%d\n",&j);
  621.             pl->levhp[i]=j;
  622.             fscanf(fp,"%d\n",&j);
  623.             pl->levsp[i]=j;
  624.             fscanf(fp,"%d\n",&j);
  625.             pl->levgrace[i]=j;
  626.           }
  627.         } else if (!strcmp(buf,"spell_array")) {
  628.           pl->nrofknownspells=value;
  629.           for(i=0;i<pl->nrofknownspells;i++) {
  630.             int j;
  631.             fscanf(fp,"%d\n",&j);
  632.             pl->known_spells[i]=j;
  633.           }
  634.         } else if (!strcmp(buf,"known_spell")) {
  635.           char *cp=strchr(bufall,'\n');
  636.           *cp='\0';
  637.           cp=strchr(bufall,' ');
  638.           cp++;
  639.           for(i=0;i<NROFREALSPELLS;i++)
  640.             if(!strcmp(spells[i].name,cp)) {
  641.               pl->known_spells[pl->nrofknownspells++]=i;
  642.               break;
  643.             }
  644.           if(i==NROFREALSPELLS)
  645.             LOG(llevDebug, "Error: unknown spell (%s)\n",cp);
  646.         } else if (!strcmp(buf,"confkeys")) {
  647.       LOG(llevDebug, "Ignoring old configkeys (%d)\n", value);
  648.           for(i=0; i < value; i++)
  649.         fgets(bufall, sizeof(bufall), fp);
  650.         } else if (!strcmp(buf,"pushkey")) {
  651.       LOG(llevDebug, "Ignoring old pushkey (%s)\n", bufall);
  652.     } else if (!strcmp(buf,"key")) {
  653.       insert_key(op->contr, KEYF_USER, &bufall[4]);
  654.         } else {
  655.             LOG(llevError,"Warning, oldfashioned variable in save-file: %s\n",
  656.                 buf);
  657.         }
  658.       }
  659.  
  660.       /* sigh */
  661.       free_object (op);
  662.       op = pl->ob = LoadObject (fp, NULL);
  663.       CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER);
  664.  
  665.       x=op->x; y=op->y;
  666.       /* if old save file, try recover from it */
  667.       if(!op->arch) {
  668.          new_draw_info(NDI_UNIQUE, 0,op,"Error: unknown class. (probably old save file)\n");
  669.          op->arch = find_archetype (op->race);
  670.       }
  671.       if(!op->arch) { /* and fail... */
  672.         new_draw_info(NDI_UNIQUE, 0,op,"Fatal error: Can't find archetype\n");
  673.         LOG(llevError, "Error: Unknown class; %s.\n", op->race);
  674.       }
  675.       strncpy(pl->title, op->arch->clone.name,MAX_NAME);
  676.  
  677.       /* If the map where the person was last saved does not exist,
  678.        * restart them in the beginning town.  This is good for when
  679.        * maps change between versions
  680.        */
  681.  
  682.       if (check_path(pl->maplevel)==-1) {
  683.     strcpy(pl->maplevel, first_map_path);
  684.     x = -1;
  685.       }
  686.  
  687.       enter_exit(op,NULL); /* This won't insert the player any longer! */
  688.       if (op->stats.hp<0||op->stats.food<0) {
  689. /* IF NOT_PERMADEATH is set, this should really do something different,
  690.  * like bring the character back to life under the normal rules.
  691.  */
  692.         clear_win_info(op);
  693.         new_draw_info(NDI_UNIQUE, 0,op,"Your character was dead, when you quit.");
  694.         new_draw_info(NDI_UNIQUE, 0,op," ");
  695.     play_again(op);
  696.         delete_character(op->name);
  697.       } else {
  698.         pl->name_changed=1;
  699.         pl->state = ST_PLAYING;
  700. #ifdef AUTOSAVE
  701.     pl->last_save_tick = pticks;
  702. #endif
  703.     op->carrying=0;
  704.     pl->freeze_inv=1;
  705.  
  706.     pl->freeze_inv=0;
  707.     if (pl->eric_server > 0) {
  708.         esrv_new_player(pl->eric_server, op->count, op->name, op->weight,
  709.             op->face->number);
  710.         esrv_send_inventory(op, op);
  711.     } else {
  712.         draw_all_inventory(op);
  713.     }
  714.  
  715.     draw_all_inventory(op);
  716.  
  717.     /* Need to call fix_player now - program modified so that it is not
  718.      * called during the load process (FLAG_NO_FIX_PLAYER set when
  719.      * saved
  720.      */
  721.     legal_range(op, op->contr->shoottype);
  722.         fix_player(op);
  723.     fix_weight ();
  724.  
  725. #ifdef ALLOW_SKILLS
  726.     (void) init_player_exp(op);
  727.         (void) link_player_skills(op);
  728. #endif
  729.  
  730.         if(!pl->split_window && pl->eric_server == 0)
  731.           XClearWindow(pl->gdisp,pl->win_root);
  732.         draw_all_info(op);
  733.         draw_all_message(op);
  734.         new_draw_info(NDI_UNIQUE, 0,op,"Welcome Back!");
  735.         if(pl->loading == NULL) {
  736.           if(!out_of_map(op->map,x,y))
  737.             op->x=x, op->y=y;
  738.           insert_ob_in_map(op,op->map);
  739.         } else {
  740.           LOG(llevError,"Warning: map was not in memory (%s).\n",
  741.                   op->map->path);
  742.           pl->removed = 0; /* Pl. will be inserted when map is loaded */
  743.         }
  744.         refresh(op);
  745.         draw_all_look(op);
  746.         close_and_delete(fp, comp);
  747.         LOG(llevDebug,"Checksums: %x %x\n",
  748.                 checksum,calculate_checksum(filename,1));
  749. #ifdef CHECKSUM_ENABLED
  750.         if(calculate_checksum(filename) != checksum) {
  751.           new_draw_info(NDI_UNIQUE, 0,op,"Since your savefile has been tampered with,");
  752.           new_draw_info(NDI_UNIQUE, 0,op,"you will not be able to save again.");
  753.           set_cheat(op);
  754.         }
  755. #endif
  756.       }
  757.     }
  758.     if (pl->state != ST_PLAYING)
  759.       close_and_delete(fp, comp); 
  760.   }
  761.   pl->last_value= -1;
  762.  
  763.   /* This seems to compile without warnings now.  Don't know if it works
  764.    * on SGI's or not, however.
  765.    */
  766.   qsort((void *)pl->known_spells,pl->nrofknownspells,
  767.     sizeof(pl->known_spells[0]),(int (*)())spell_sort);
  768.   draw_stats(op);
  769. #ifdef SAVE_WINDOW_POSITIONS
  770.   if(pl->valid_save_positions && pl->split_window) {
  771.     unsigned long xwc_mask=0;
  772.     XWindowChanges xwc;
  773.     xwc_mask=CWX|CWY|CWWidth|CWHeight;
  774.     
  775.     xwc.x=pl->win_pos[0].x;xwc.y=pl->win_pos[0].y;
  776.     xwc.width=pl->win_pos[0].w;xwc.height=pl->win_pos[0].h;
  777.     XConfigureWindow(pl->gdisp,pl->win_game,xwc_mask,&xwc);
  778.  
  779.     xwc.x=pl->win_pos[1].x;xwc.y=pl->win_pos[1].y;
  780.     xwc.width=pl->win_pos[1].w;xwc.height=pl->win_pos[1].h;
  781.     XConfigureWindow(pl->gdisp,pl->win_stats,xwc_mask,&xwc);
  782.  
  783.     xwc.x=pl->win_pos[2].x;xwc.y=pl->win_pos[2].y;
  784.     xwc.width=pl->win_pos[2].w;xwc.height=pl->win_pos[2].h;
  785.     XConfigureWindow(pl->gdisp,pl->win_info,xwc_mask,&xwc);
  786.  
  787.     xwc.x=pl->win_pos[3].x;xwc.y=pl->win_pos[3].y;
  788.     xwc.width=pl->win_pos[3].w;xwc.height=pl->win_pos[3].h;
  789.     XConfigureWindow(pl->gdisp,pl->win_inv,xwc_mask,&xwc);
  790.  
  791.     xwc.x=pl->win_pos[4].x;xwc.y=pl->win_pos[4].y;
  792.     xwc.width=pl->win_pos[4].w;xwc.height=pl->win_pos[4].h;
  793.     XConfigureWindow(pl->gdisp,pl->win_look,xwc_mask,&xwc);
  794.  
  795.     xwc.x=pl->win_pos[5].x;xwc.y=pl->win_pos[5].y;
  796.     xwc.width=pl->win_pos[5].w;xwc.height=pl->win_pos[5].h;
  797.     XConfigureWindow(pl->gdisp,pl->win_message,xwc_mask,&xwc);
  798.   }
  799.     
  800. #endif /* SAVE_WINDOW_POSITIONS */
  801.   return;
  802. }
  803.   
  804.  
  805.